package xyz.tanxiao.links.common.utils;

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.util.unit.DataSize;
import org.springframework.web.multipart.MultipartFile;
import xyz.tanxiao.links.common.entity.BatchTaskResult;
import xyz.tanxiao.links.common.exception.ToShortLinkException;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.*;

/**
 * 批量生成短链接工具类
 *
 * @author 万成波
 * @email 2300064869@qq.com
 * @createTime 2023-07-20 23:54:02 星期四
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BatchTaskUtils {

	private static final String BATH_FILE_TYPE = ".xlsx";

	private static final int DIVISOR_SIZE_MB = 1024 * 1024;


	/**
	 * 检查包含了长连接的文本文件
	 *
	 * @param file 文本文件
	 * @param fileMaxSize 文本文件最大大小 (MB)
	 */
	public static void checkFile(MultipartFile file, DataSize fileMaxSize) {
		// 文件校验
		if (Objects.isNull(file)) {
			throw new ToShortLinkException("短链批量生成失败，请上传包含原始链接的文本文件。");
		}
		// 文件格式校验
		String filename = file.getOriginalFilename();
		if (Objects.isNull(filename) || !filename.endsWith(".txt")) {
			throw new ToShortLinkException("短链批量生成失败，请上传包含原始链接的文本文件。");
		}
		// 文件大小校验
		long maxSize = fileMaxSize.toMegabytes();
		if ((file.getSize() / DIVISOR_SIZE_MB) > maxSize) {
			throw new ToShortLinkException("短链批量生成失败，请上传文本文件不能超过" + maxSize + "MB。");
		}
	}


	/**
	 * 读取文本文件内的所有长链接
	 *
	 * @param file 文本文件
	 * @return 长链接列表
	 */
	public static List<String> readFile(MultipartFile file) {
		Set<String> longLinks = new LinkedHashSet<>(10);
		try (
			BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))
		) {
			String longLink;
			while (StringUtils.hasText(longLink = reader.readLine())) {
				longLinks.add(longLink);
			}
		} catch (Exception e){
			log.error("=> 读取长链接文本文件错误：" + e.getMessage());
		}
		return new ArrayList<>(longLinks);
	}


	/**
	 * 写入短链生成的短链数据到Excel
	 *
	 * @param taskId 批量生成任务标识
	 * @param results 批量生成任务结果
	 * @param saveDir 生成文件保存路径
	 * @return 短链数据文件
	 */
	public static String writeFile(String taskId, List<BatchTaskResult> results, String saveDir) {
		// 写入表格数据
		List<Map<String, Object>> dataItems = new ArrayList<>(results.size());
		results.forEach(result -> {
			Map<String, Object> dataItem = new LinkedHashMap<>(9);
			dataItem.put("长链接", result.getLongLink());
			dataItem.put("生成结果", result.getResult());
			dataItem.put("生成信息", result.getResultInfo());
			dataItem.put("生成数量", result.getTotal());
			dataItem.put("映射Key", result.getMappingKeys().toString());
			dataItem.put("短链地址", result.getShortLinks().toString());
			dataItem.put("启用时间", result.getEnableTime());
			dataItem.put("过期时间", result.getDisableTime());
			dataItem.put("可用次数", result.getAllowTotal());
			dataItem.put("访问密码", result.getAccessPassword());
			dataItems.add(dataItem);
		});

		String fileName = taskId + BATH_FILE_TYPE;
		ExcelWriter writer = ExcelUtil.getWriter(new File(saveDir + fileName));
		// 单元格列宽
		writer.setColumnWidth(0, 40);
		writer.setColumnWidth(1, 10);
		writer.setColumnWidth(2, 20);
		writer.setColumnWidth(3, 10);
		writer.setColumnWidth(4, 30);
		writer.setColumnWidth(5, 50);
		writer.setColumnWidth(6, 20);
		writer.setColumnWidth(7, 20);
		writer.setColumnWidth(8, 10);
		writer.setColumnWidth(9, 15);
		// 写入文件
		writer.write(dataItems, true);
		writer.close();
		return fileName;
	}

}
